package atom.core1.object;

import java.beans.PropertyDescriptor;   
import java.text.SimpleDateFormat;   
import java.util.Collection;   
  
import org.apache.commons.beanutils.PropertyUtils;   
import org.apache.log4j.Logger;   
  
/**  
 * <strong>复制处理类</strong>  
 */  
public class CopyUtil {   
    private static final Logger log = Logger.getLogger(CopyUtil.class.getName());   
  
    /**  
     * 复制orig属性值赋值给dest  
     * <p>  
     * 满足如下条件时进行复制处理：  
     * (1) dest与orig的属性名称相同；  
     * (2) dest与orig的属性类型相同；  
     * (3) dest的属性类型不为Class；  
     * (4) orig属性类型不是Collection或者不是Collection的超类或接口；  
     * </p>  
     *  
     * @param dest 目标对象  
     * @param orig 源对象  
     * @return 如果dest或者orig为null则返回null/如果发生异常返回null/否则返回复制填充后的dest  
     */  
    public static Object copyProperties(Object dest, Object orig) {   
        if (dest == null || orig == null) {   
            return dest;   
        }   
        PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);   
        try {   
            for (int i = 0; i < destDesc.length; i++) {   
                Class destType = destDesc[i].getPropertyType();   
                Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());   
                if (destType != null && destType.equals(origType) && !destType.equals(Class.class)) {   
                    if (!Collection.class.isAssignableFrom(origType)) {   
                        try {   
                            Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());   
                            PropertyUtils.setProperty(dest, destDesc[i].getName(), value);   
                        } catch (Exception ex) {   
                            log.error("copyProperties(Object dest, Object orig)循环中异常。", ex);   
                        }   
                    }   
                }   
            }   
  
            return dest;   
        } catch (Exception ex) {   
            log.error("copyProperties(Object dest, Object orig)异常。", ex);   
            return null;   
        }   
    }   
    public static Object copyNotNullProperties(Object dest, Object orig) {   
        if (dest == null || orig == null) {   
            return dest;   
        }   
        PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);   
        try {   
            for (int i = 0; i < destDesc.length; i++) {   
                Class destType = destDesc[i].getPropertyType();   
                Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());   
                if (destType != null && destType.equals(origType) && !destType.equals(Class.class)) {   
                    if (!Collection.class.isAssignableFrom(origType)) {   
                        try {   
                            Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());   
                            if (value!=null)
                            	PropertyUtils.setProperty(dest, destDesc[i].getName(), value);   
                        } catch (Exception ex) {   
                            log.error("copyProperties(Object dest, Object orig)循环中异常。", ex);   
                        }   
                    }   
                }   
            }   
  
            return dest;   
        } catch (Exception ex) {   
            log.error("copyProperties(Object dest, Object orig)异常。", ex);   
            return null;   
        }   
    }   
  
    /**  
     * 复制orig属性值赋值给dest  
     * <p>  
     * 除了将String的值转换为java.util.Date的处理外，其他处理方式同copyProperties(Object dest, Object orig)。  
     * 最常用在将页面的查询条件（Form）转换为DTO进行数据库查询的处理。  
     * </p>  
     *  
     * @param dest 目标对象  
     * @param orig 源对象  
     * @return 如果dest或者orig为null则返回null/如果发生异常返回null/否则返回复制填充后的dest  
     */  
    public static Object copyPropertiesSpecialOfStringToDate(Object dest, Object orig) {   
        if (dest == null || orig == null) {   
            return dest;   
        }   
        PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);   
        try {   
            for (int i = 0; i < destDesc.length; i++) {   
                Class destType = destDesc[i].getPropertyType();   
                Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());   
                if (destType != null && origType != null && !destType.equals(Class.class)) {   
                    if (origType.equals(destType)) {   
                        if (!Collection.class.isAssignableFrom(origType)) {   
                            try {   
                                Object valueOrig = PropertyUtils.getProperty(orig, destDesc[i].getName());   
                                PropertyUtils.setProperty(dest, destDesc[i].getName(), valueOrig);   
                            } catch (Exception ex) {   
                                log.error("copyPropertiesSpecialOfStringToDate循环中异常-1。", ex);   
                                PropertyUtils.setProperty(dest, destDesc[i].getName(), null);   
                            }   
                        }   
                    } else if (destType.equals(java.util.Date.class) && origType.equals(String.class)) {   
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");   
                        try {   
                            String valueOrig_string = (String) PropertyUtils.getProperty(orig, destDesc[i].getName());   
                            if (valueOrig_string != null && valueOrig_string.trim().length() > 0) {   
                                PropertyUtils.setProperty(dest, destDesc[i].getName(), format.parse(valueOrig_string));   
                            } else {   
                                PropertyUtils.setProperty(dest, destDesc[i].getName(), null);   
                            }   
                        } catch (Exception e) {   
                            log.error("copyPropertiesSpecialOfStringToDate循环中异常-2。", e);   
                            PropertyUtils.setProperty(dest, destDesc[i].getName(), null);   
                        }   
                    }   
                }   
            }   
            return dest;   
        } catch (Exception e) {   
            log.error("copyPropertiesSpecialOfStringToDate异常。", e);   
            return null;   
        }   
    }   
  
    /**  
     * 复制orig中指定的属性值赋值给dest  
     * <p>  
     * 除了指定属性名称数组外，其他处理方式同copyProperties(Object dest, Object orig)。  
     * </p>  
     *  
     * @param dest  
     * @param orig  
     * @param ignores  
     * @return  
     */  
    public static Object copyProperties(Object dest, Object orig, String[] ignores) {   
        if (dest == null || orig == null) {   
            return dest;   
        }   
  
        PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);   
        try {   
            for (int i = 0; i < destDesc.length; i++) {   
  
                if (contains(ignores, destDesc[i].getName())) {   
                    continue;   
                }   
  
                Class destType = destDesc[i].getPropertyType();   
                Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());   
  
                if (destType != null && destType.equals(origType) && !destType.equals(Class.class)) {   
                    if (!Collection.class.isAssignableFrom(origType)) {   
                        Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());   
                        PropertyUtils.setProperty(dest, destDesc[i].getName(), value);   
                    }   
                }   
            }   
  
            return dest;   
        } catch (Exception ex) {   
            return null;   
        }   
    }   
  
    /**  
     * 属性名称数组中是否存在指定的属性  
     *  
     * @param ignores 属性名称数组  
     * @param name 指定的属性名称  
     * @return 如果存在则返回true/否则返回false  
     */  
    static boolean contains(String[] ignores, String name) {   
        boolean ignored = false;   
        for (int j = 0; ignores != null && j < ignores.length; j++) {   
            if (ignores[j].equals(name)) {   
                ignored = true;   
                break;   
            }   
        }   
        return ignored;   
    }   
}  

